package com.threeti.mecool.core.domain.model.plan;

import com.threeti.mecool.core.domain.model.acl.User;
import com.threeti.mecool.core.domain.model.basicdata.biz.ChannelSync;
import com.threeti.mecool.core.domain.model.plan.pojo.PlanJob;
import com.threeti.mecool.core.domain.model.plan.pojo.Step;
import com.threeti.mecool.core.domain.model.project.ProjectEmployee;
import com.threeti.mecool.core.infrastructure.persistence.acl.UserRepository;
import com.threeti.mecool.core.infrastructure.persistence.basicdata.biz.ChannelSyncRepository;
import com.threeti.mecool.core.infrastructure.persistence.plan.UserStepResultRepository;
import com.threeti.mecool.core.infrastructure.persistence.project.ProjectEmployeeRepository;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.data.domain.Sort;

import javax.annotation.Resource;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Configurable
@Entity
@Table(name = "DM_WF_PLAN_JOB_RESULT")
public class PlanJobResult {
    public static final String JOB_STATUS_FINISHED = "FINISHED";
    public static final String JOB_STATUS_NOT_FINISHED = "NOT_FINISHED";
    /** 逻辑判断，状态字段中没有此字符串文本 **/
    public static final String JOB_STATUS_DELAYED = "DELAYED";
    private Long id;
    private Integer version;
    private PlanResult planResult;
    private PlanJob planJob;
    private List<UserStepResult> userStepResults = new ArrayList<UserStepResult>();
    private Date finishedAt;
    private ChannelSyncRepository channelSyncRepo;
    private ProjectEmployeeRepository projEmpRepo;
    private UserStepResultRepository userStepResultRepository;
    private UserRepository userRepo;
    private String jobStatus = PlanJobResult.JOB_STATUS_NOT_FINISHED;
    private String notes;

    private String jobName;
    private String jobCode;
    private String projectCode;
    private String projectName;
    private String storeCode;
    //    private String storeChannelAdName;
//    private String storeChannelAdCode;
//    private String storeChannelProvinceAdName;
//    private String storeChannelProvinceAdCode;
//    private String storeChannelCityAdName;
//    private String storeChannelCityAdCode;
//    private String storeChannelName;
//    private String storeChannelAddress;
    private ChannelSync channel;

    private String empId;
    private String empName;
    private String projEmpTitle;

    //gps related->
    private Date planJobStartTime;
    private Date planJobEndTime;
    private String jobStartedLongitude;
    private String jobStartedLatitude;
    private String jobFinishedLongitude;
    private String jobFinishedLatitude;
    //<-

    // <-
    private PlanJobResultAuditStatus auditStatus = PlanJobResultAuditStatus.HASNT_BEEN_AUDITED;

    public UserStepResult optUserStepResult(Long stepId) {
        for (UserStepResult userStepResult : userStepResults) {
            if (stepId.equals(userStepResult.getStep().getId())) {
                return userStepResult;
            }
        }
        UserStepResult userStepResult = new UserStepResult();
        Step step = Step.findById(stepId);
        userStepResult.setStep(step);
        userStepResult.setPlanJobResult(this);
        userStepResult.setUserLoginName(userStepResult.getPlanJobResult().getPlanResult().getPlan().getUserLoginName());
        userStepResult.setActionId(step.getTask().getAction().getId());
        //<-
        userStepResult.setDataTypeId(step.getTask().getDataTypeId());
        userStepResults.add(userStepResult);
        saveRedundantProperties();

        userStepResult.saveRedundantProperties();

        return userStepResult;
    }

    @Transient
    public UserStepResult getFirstUserStepResult() {
        if (finishedAt != null && JOB_STATUS_FINISHED.equals(jobStatus)) {
            if (userStepResults.size() == 0) {
                userStepResults = userStepResultRepository.findByPlanJobResult(this, new Sort(Sort.Direction.ASC, "finishedAt"));
                if (userStepResults.size() > 0) {
                    return userStepResults.get(0);
                }
            }
            UserStepResult firstStep = null;
            for (UserStepResult userStepResult : userStepResults) {
                if (firstStep == null || userStepResult.getFinishedAt().before(firstStep.getFinishedAt())) {
                    firstStep = userStepResult;
                }
            }
            return firstStep;
        }
        return null;
    }

    @Transient
    public UserStepResult getLastUserStepResult() {
        if (finishedAt != null && JOB_STATUS_FINISHED.equals(jobStatus) && userStepResults.size() > 0) {
            UserStepResult lastStep = null;
            for (UserStepResult userStepResult : userStepResults) {
                if (lastStep == null || userStepResult.getFinishedAt().after(lastStep.getFinishedAt())) {
                    lastStep = userStepResult;
                }
            }
            return lastStep;
        }
        return null;
    }

    // <editor-fold desc="get/set">
    @Resource
    public void setProjEmpRepo(ProjectEmployeeRepository projEmpRepo) {
        this.projEmpRepo = projEmpRepo;
    }

    @Resource
    public void setUserRepo(UserRepository userRepo) {
        this.userRepo = userRepo;
    }

    @Resource
    public void setChannelSyncRepo(ChannelSyncRepository channelSyncRepo) {
        this.channelSyncRepo = channelSyncRepo;
    }

    @Resource
    public void setUserStepResultRepository(UserStepResultRepository userStepResultRepository) {
        this.userStepResultRepository = userStepResultRepository;
    }

    @Id
    @GeneratedValue
    public Long getId() {
        return id;
    }

    @Version
    public Integer getVersion() {
        return version;
    }

    @ManyToOne
    public PlanResult getPlanResult() {
        return planResult;
    }

    @ManyToOne(fetch = FetchType.EAGER)
    public ChannelSync getChannel() {
        return channel;
    }

    public void setChannel(ChannelSync channel) {
        this.channel = channel;
    }

    @OneToOne
    public PlanJob getPlanJob() {
        return planJob;
    }

    @OneToMany(mappedBy = "planJobResult", cascade = CascadeType.ALL, orphanRemoval = true)
    public List<UserStepResult> getUserStepResults() {
        return userStepResults;
    }

    @Temporal(TemporalType.TIMESTAMP)
    public Date getFinishedAt() {
        return finishedAt;
    }

    public String getJobName() {
        if (jobName == null || jobName.isEmpty()) {
            if (planJob != null && planJob.getJob() != null)
                jobName = planJob.getJob().getName();
        }
        return jobName;
    }

    public String getProjectCode() {
        if (projectCode == null || projectCode.isEmpty()) {
            if (planJob != null && planJob.getPlanProject() != null)
                projectCode = planJob.getPlanProject().getProjectCode();
        }
        return projectCode;
    }

    public String getStoreCode() {
        return storeCode;
    }

    @Transient
    public String getStoreChannelAdName() {
        return channel == null ? "" : channel.getAdName();
    }

    @Transient
    public String getStoreChannelAdCode() {
        return channel == null ? "" : channel.getAdCode();
    }

    @Transient
    public String getStoreChannelProvinceAdName() {
        return channel == null ? "" : channel.getProvinceAdName();
    }

    @Enumerated(EnumType.ORDINAL)
    public PlanJobResultAuditStatus getAuditStatus() {
        return auditStatus;
    }

    @Transient
    public String getStoreChannelProvinceAdCode() {
        return channel == null ? "" : channel.getProvinceAdCode();
    }

    @Transient
    public String getStoreChannelCityAdName() {
        return channel == null ? "" : channel.getCityAdName();
    }

    @Transient
    public String getStoreChannelCityAdCode() {
        return channel == null ? "" : channel.getCityAdCode();
    }

    @Transient
    public String getStoreChannelName() {
        return channel == null ? "" : channel.getName();
    }

    @Transient
    public String getStoreChannelAddress() {
        return channel == null ? "" : channel.getAddress();
    }

    public String getJobStatus() {
        return jobStatus;
    }

    public String getNotes() {
        return notes;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public void setVersion(Integer version) {
        this.version = version;
    }

    public void setPlanResult(PlanResult planResult) {
        this.planResult = planResult;
    }

    public void setPlanJob(PlanJob planJob) {
        this.planJob = planJob;
    }

    public void setUserStepResults(List<UserStepResult> userStepResults) {
        this.userStepResults = userStepResults;
    }

    public void setFinishedAt(Date finishedAt) {
        this.finishedAt = finishedAt;
    }

    public void setJobName(String jobName) {
        this.jobName = jobName;
    }

    public String getJobCode() {
        return jobCode;
    }

    public void setJobCode(String jobCode) {
        this.jobCode = jobCode;
    }

    public void setProjectCode(String projectCode) {
        this.projectCode = projectCode;
    }

    public String getProjectName() {
//        if (projectName == null || projectName.isEmpty()) {
//            if (planJob != null && planJob.getPlanProject() != null)
//                projectName = planJob.getPlanProject().getProjectName();
//        }
        return projectName;
    }

    public void setProjectName(String projectName) {
        this.projectName = projectName;
    }

    public void setStoreCode(String storeCode) {
        this.storeCode = storeCode;
    }

    public void setStoreChannelAdName(String storeChannelAdName) {
        if (channel == null) return;
        channel.setAdName(storeChannelAdName);
    }

    public void setStoreChannelAdCode(String storeChannelAdCode) {
        if (channel == null) return;
        channel.setAdCode(storeChannelAdCode);
    }

    public void setAuditStatus(PlanJobResultAuditStatus auditStatus) {
        this.auditStatus = auditStatus;
    }


    public void setStoreChannelProvinceAdName(String storeChannelProvinceAdName) {
        if (channel == null) return;
        channel.setProvinceAdName(storeChannelProvinceAdName);
    }

    public void setStoreChannelProvinceAdCode(String storeChannelProvinceAdCode) {
        if (channel == null) return;
        channel.setProvinceAdCode(storeChannelProvinceAdCode);
    }

    public void setStoreChannelCityAdName(String storeChannelCityAdName) {
        if (channel == null) return;
        channel.setCityAdName(storeChannelCityAdName);
    }

    public void setStoreChannelCityAdCode(String storeChannelCityAdCode) {
        if (channel == null) return;
        channel.setCityAdCode(storeChannelCityAdCode);
    }

    public void setStoreChannelName(String storeChannelName) {
        if (channel == null) return;
        channel.setName(storeChannelName);
    }

    public void setStoreChannelAddress(String storeChannelAddress) {
        if (channel == null) return;
        channel.setAddress(storeChannelAddress);
    }

    public String getEmpId() {
        return empId;
    }

    public void setEmpId(String empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String projEmpName) {
        this.empName = projEmpName;
    }

    public String getProjEmpTitle() {
        return projEmpTitle;
    }

    public void setProjEmpTitle(String projEmpTitle) {
        this.projEmpTitle = projEmpTitle;
    }

    @Temporal(TemporalType.TIMESTAMP)
    public Date getPlanJobStartTime() {
        return planJobStartTime;
    }

    public void setPlanJobStartTime(Date planJobStartTime) {
        this.planJobStartTime = planJobStartTime;
    }

    @Temporal(TemporalType.TIMESTAMP)
    public Date getPlanJobEndTime() {
        return planJobEndTime;
    }

    public void setPlanJobEndTime(Date planJobEndTime) {
        this.planJobEndTime = planJobEndTime;
    }

    /**
     * Job完成时记录的地理位置经度
     */
    public String getJobFinishedLongitude() {
        return jobFinishedLongitude;
    }

    public void setJobFinishedLongitude(String finishedLongitude) {
        this.jobFinishedLongitude = finishedLongitude;
    }

    /**
     * Job完成时记录的地理位置纬度
     */
    public String getJobFinishedLatitude() {
        return jobFinishedLatitude;
    }

    public void setJobFinishedLatitude(String finishedLatitude) {
        this.jobFinishedLatitude = finishedLatitude;
    }

    /**
     * Job开始时记录的地理位置经度
     */
    public String getJobStartedLongitude() {
        return jobStartedLongitude;
    }

    public void setJobStartedLongitude(String startLongitude) {
        this.jobStartedLongitude = startLongitude;
    }

    /**
     * Job开始时记录的地理位置纬度
     */
    public String getJobStartedLatitude() {
        return jobStartedLatitude;
    }

    public void setJobStartedLatitude(String startLatitude) {
        this.jobStartedLatitude = startLatitude;
    }

    public void setNotes(String notes) {
        this.notes = notes;
    }

    public void setJobStatus(String jobStatus) {
        this.jobStatus = jobStatus;
    }
    // </editor-fold>

    public PlanJobResult() {
    }

    public PlanJobResult(String jobName, String empId, String empName, String projectCode, String projectName, String storeCode, ChannelSync channelSync) {
        super();
        this.jobName = jobName;
        this.empId = empId;
        this.empName = empName;
        this.projectCode = projectCode;
        this.projectName = projectName;
        this.storeCode = storeCode;
        this.channel = channelSync;
//        this.storeChannelAdName = storeChannelAdName;
//        this.storeChannelAdCode = storeChannelAdCode;
//        this.storeChannelProvinceAdName = storeChannelProvinceAdName;
//        this.storeChannelProvinceAdCode = storeChannelProvinceAdCode;
//        this.storeChannelCityAdName = storeChannelCityAdName;
//        this.storeChannelCityAdCode = storeChannelCityAdCode;
//        this.storeChannelName = storeChannelName;
//        this.storeChannelAddress = storeChannelAddress;
    }

    public PlanJobResult(String jobName, String jobCode, String empId, String empName, String projectCode, String projectName, String storeCode, ChannelSync channelSync) {
        super();
        this.jobName = jobName;
        this.jobCode = jobCode;
        this.empId = empId;
        this.empName = empName;
        this.projectCode = projectCode;
        this.projectName = projectName;
        this.storeCode = storeCode;
        this.channel = channelSync;
//        this.storeChannelAdName = storeChannelAdName;
//        this.storeChannelAdCode = storeChannelAdCode;
//        this.storeChannelProvinceAdName = storeChannelProvinceAdName;
//        this.storeChannelProvinceAdCode = storeChannelProvinceAdCode;
//        this.storeChannelCityAdName = storeChannelCityAdName;
//        this.storeChannelCityAdCode = storeChannelCityAdCode;
//        this.storeChannelName = storeChannelName;
//        this.storeChannelAddress = storeChannelAddress;
    }

//    public void assignFrom(PlanJob planJob) {
//        jobName = planJob.getJob().getName();
//        projectCode = planJob.getPlanProject().getProjectCode();
//        projectName = planJob.getPlanProject().getProjectName();
//        this.planJob = planJob;
//        saveRedundantProperties();
//    }

    void saveRedundantProperties() {
        if (getPlanJob() != null) {
            if (getPlanJob().getJob() != null) {
                jobCode = getPlanJob().getJob().getCode();
            }
            try {
                String userLoginName = getPlanJob().getPlanProject().getPlan().getUserLoginName();
                User userJobAssignedTo = userRepo.findByloginName(userLoginName);
                if (projectCode != null) {
                    ProjectEmployee projEmp = projEmpRepo.findByProjectCodeAndEmpId(projectCode, userJobAssignedTo.getEmployee().getEmpId());
                    this.empId = String.valueOf(projEmp.getEmpId());
                    this.empName = projEmp.getEmpName();
                    this.projEmpTitle = projEmp.getTitleWithinTheProject();
                }

                String channelCode = getPlanJob().getStoreCode();
                this.channel = channelSyncRepo.findByChannelCode(channelCode);
                if (channel != null) {
                    storeCode = channel.getCode();
//                storeChannelAdName = channel.getAdName();
//                storeChannelAdCode = channel.getAdCode();
//                storeChannelProvinceAdName = channel.getProvinceAdName();
//                storeChannelProvinceAdCode = channel.getProvinceAdCode();
//                storeChannelCityAdName = channel.getCityAdName();
//                storeChannelCityAdCode = channel.getCityAdCode();
//                storeChannelName = channel.getName();
//                storeChannelAddress = channel.getAddress();

                }

                if (getPlanJob().getPlanProject() != null && getPlanJob().getPlanProject().getPlan() != null && getPlanJob().getPlanProject().getPlan().getPlanDate() != null) {
                    DateTime tempPlanDate = new DateTime(getPlanJob().getPlanProject().getPlan().getPlanDate());
                    DateTime tempStartTime = new DateTime(getPlanJob().getStartTime());
                    DateTime tempEndTime = new DateTime(getPlanJob().getEndTime());
                    tempStartTime = tempStartTime.withDate(tempPlanDate.getYear(), tempPlanDate.getMonthOfYear(), tempPlanDate.getDayOfMonth());
                    tempEndTime = tempEndTime.withDate(tempPlanDate.getYear(), tempPlanDate.getMonthOfYear(), tempPlanDate.getDayOfMonth());
                    planJobStartTime = tempStartTime.toDate();
                    planJobEndTime = tempEndTime.toDate();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
